package com.eunion.web.admin.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.validation.Valid;

import com.eunion.boot.spring.SpringUtil;
import org.apache.commons.lang3.StringUtils;
//import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Scope;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.eunion.boot.security.SpringSecurityUtil;
import com.eunion.core.LogUtil;
import com.eunion.core.PageConditions;
import com.eunion.core.PageData;
import com.eunion.core.common.DeleteVo;
import com.eunion.core.common.JsonVo;
import com.eunion.core.common.KvVo;
import com.eunion.core.exception.ValidateException;
import com.eunion.web.admin.bo.AdminUserRoleBo;
import com.eunion.web.admin.entity.AdminUser;
import com.eunion.web.admin.service.AdminRoleService;
import com.eunion.web.admin.service.AdminUserService;
import com.eunion.web.admin.vo.JsonMapVo;
import com.eunion.web.common.base.BaseService;
import com.eunion.web.common.base.BaseTableCommonController;
import com.eunion.web.common.base.search.SearchOperator;
import com.eunion.web.common.vo.Web;
import com.eunion.common.util.CommUtils;

/**
 * 用户的管理.
 *
 * @version 2016年10月17日
 */
@Controller
@RequestMapping(value = "/admin/adminuser")
public class AdminUserController extends BaseTableCommonController<AdminUser, String> {

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private AdminUserService adminUserService;

    @Autowired
    private AdminRoleService adminRoleService;

    /**
     * 根据前台头面生成查询条件.
     *
     * @param params 参数
     * @return 返回查询条件
     */
    protected Specification<AdminUser> getCondition(final PageData<AdminUser> params) {
        return new Specification<AdminUser>() {

            //eq , like
            private Predicate getCriteriaBuilder(CriteriaBuilder cb, Root<AdminUser> root, PageConditions pc) {
                Predicate pr = null;
                // 确保数据有效
                if (pc != null && StringUtils.isNotEmpty(pc.getKey()) && null != pc.getType() && null != pc.getValue()) {
                    if (pc.getOperator().equalsIgnoreCase(SearchOperator.Conditon.eq)) {
                        pr = cb.equal(root.get(pc.getKey()), pc.getValue());
                    } else if (pc.getOperator().equalsIgnoreCase(SearchOperator.Conditon.like)) {
                        if (pc.getType().equalsIgnoreCase(SearchOperator.Type.string)) {
                            pr = cb.like(root.<String>get(pc.getKey()), "%" + pc.getValue() + "%");
                        }
                    } else if (pc.getOperator().equalsIgnoreCase(SearchOperator.Conditon.ge)) {
                        if (pc.getType().equalsIgnoreCase(SearchOperator.Type.string)) {
                            pr = cb.greaterThanOrEqualTo(root.<String>get(pc.getKey()), (String) pc.getValue());
                        } else if (pc.getType().equalsIgnoreCase(SearchOperator.Type.intger)) {
                            pr = cb.greaterThanOrEqualTo(root.<Integer>get(pc.getKey()), (Integer) pc.getValue());
                        }
                    }

                }
                return pr;
            }

            @Override
            public Predicate toPredicate(Root<AdminUser> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> list = new ArrayList<Predicate>();
                List<PageConditions> conditions = params.getConditions();
                if (conditions != null && conditions.size() > 0) {
                    Date start = null;
                    Date end = null;
                    for (PageConditions pc : conditions) {
                        LOG.debug("search PageConditions is :{}", pc);

                        if (pc.getKey().equals("createdTimeB") && null != pc.getValue()) {
                            Date date = CommUtils.strToDateLong(pc.getValue().toString());
                            start = date;
                        } else if (pc.getKey().equals("createdTimeE") && null != pc.getValue()) {
                            Date date = CommUtils.strToDateLong(pc.getValue().toString());
                            end = date;
                        } else {
                            Predicate pr = getCriteriaBuilder(cb, root, pc);
                            if (pr != null) {
                                LOG.debug("search PageConditions is added:{}", pc);
                                list.add(pr);
                            }
                        }
      
						/*
      if (pc.getKey().equals("createdTimeB") && null != pc.getValue()) {
							Date date = CommUtils.strToDateLong(pc.getValue().toString());
							if (null != date) {
								Predicate p2 = cb.greaterThanOrEqualTo((Path<Date>) root.<Date> get("createdTime"), date);
								list.add(p2);
							}
						} else if (pc.getKey().equals("createdTimeE") && null != pc.getValue()) {
							Date date = CommUtils.strToDateLong(pc.getValue().toString());
							if (null != date) {
								Predicate p2 = cb.lessThanOrEqualTo((Path<Date>) root.<Date> get("timeCreate"), date);
								list.add(p2);
							}
						} else {
							Predicate pr = getCriteriaBuilder(cb, root, pc);
							if (pr != null) {
								LOG.debug("search PageConditions is added:{}", pc);
								list.add(pr);
							}
						}*/
                    }

                    if (start != null && end == null) {
                        Predicate p2 = cb.greaterThan((Path<Date>) root.<Date>get("createdTime"), start);
                        list.add(p2);
                    } else if (start == null && end != null) {
                        Predicate p2 = cb.lessThan((Path<Date>) root.<Date>get("createdTime"), end);
                        list.add(p2);
                    } else if (start != null && end != null) {
                        Predicate p2 = cb.between((Path<Date>) root.<Date>get("createdTime"), start, end);
                        list.add(p2);
                    }

                }
                Predicate admin = cb.notEqual((Path<String>) root.<String>get("username"), "admin");
                list.add(admin);
                Predicate[] p = new Predicate[list.size()];
                query.where(cb.and(list.toArray(p)));
                setOrder(root, query, cb, params);
                return query.getRestriction();
            }
        };
    }

    //	@RequiresPermissions("admin:user:main")
    @PreAuthorize("hasAuthority('admin:user:main')")
    @Override
    @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST})
    public String main(PageData<AdminUser> pages, Model model) {
        setModuleQuery(model);
        model.addAttribute("pages", pages);
        return getUrlBase();
    }

    /**
     * Post 保存对象.
     */
    @PreAuthorize("hasAuthority('admin:user:add')")
    @RequestMapping(value = Web.URL_SEP_SAVE, method = {RequestMethod.POST})
    private String save(@Valid AdminUser obj, BindingResult result, Model model) {
        try {
            checkBindResult(result);//检查bindingresult中是否有异常.
            if (StringUtils.isNotEmpty(obj.getMobile()) && !CommUtils.isMobile(obj.getMobile())) {
                throw new ValidateException("请输入正确的手机号码");
            }
            if (StringUtils.isNotEmpty(obj.getEmail()) && !CommUtils.isEmail(obj.getEmail())) {
                throw new ValidateException("请输入正确的邮箱");
            }
            AdminUser objDb = null;
            try {
                objDb = adminUserService.findOne(obj.getUsername());
            } catch (Throwable throwable) {
            }
            if (null != objDb) {
                setModuleAdd(model);
                setModuleStatusError(model, "用户名称已存在!");
                return getUrlBase().concat("-add");
            }
            obj.setPassword(CommUtils.getMd5("123456"));
            obj.setCreatedTime(CommUtils.getDayTimestamp());
            obj.setCreatedBy(getSessionUserName());
            setModuleStatusOK(model);
            getBaseService().save(obj);
            //model.addAttribute(Web.OBJ, new AdminUser());
            setModuleStatusOK(model, "新增成功,初始密码为123456");
        } catch (ValidateException ve) {
            model.addAttribute(Web.OBJ, obj);
            setModuleStatusError(model, ve.getMsg());
        } catch (Exception e) {
            model.addAttribute(Web.OBJ, obj);
            LogUtil.get(this.getClass()).error("save obj error : {}", e);
            setModuleStatusError(model, "新增失败");
        }
        setModuleAdd(model);
        return getUrlBase().concat("-add");
    }

    /**
     * Post 更新对象.
     */
//	@RequiresPermissions("admin:user:edit")
    @PreAuthorize("hasAuthority('admin:user:edit')")
    @RequestMapping(value = Web.URL_SEP_UPDATE, method = {RequestMethod.POST})
    private String update(@Valid AdminUser obj, BindingResult result, Model model) {
        try {
            checkBindResult(result);//检查bindingresult中是否有异常.
            if (StringUtils.isNotEmpty(obj.getMobile()) && !CommUtils.isMobile(obj.getMobile())) {
                throw new ValidateException("请输入正确的手机号码");
            }
            if (StringUtils.isNotEmpty(obj.getEmail()) && !CommUtils.isEmail(obj.getEmail())) {
                throw new ValidateException("请输入正确的邮箱");
            }
            
            if (adminUserService == null) {
                adminUserService = (AdminUserService)getBaseService();
            }
            AdminUser objDb = adminUserService.findOne(obj.getUsername());
            if (objDb == null) {
                setModuleAdd(model);
                setModuleStatusError(model, "用户不存在!");
                model.addAttribute(Web.OBJ, obj);
                return getUrlBase().concat("-edit");
            }
            objDb.setUpdatedTime(CommUtils.getDayTimestamp());
            objDb.setUpdatedBy(getSessionUserName());
            if (StringUtils.isNotBlank(obj.getMobile())) {
                objDb.setMobile(obj.getMobile());
            }
            if (StringUtils.isNotBlank(obj.getEmail())) {
                objDb.setEmail(obj.getEmail());
            }
            if (null != obj.getStatus()) {
                objDb.setStatus(obj.getStatus());
            }

            setModuleStatusOK(model);
            getBaseService().save(objDb);
            setModuleStatusOK(model, "更新成功");
        } catch (ValidateException ve) {
            setModuleStatusError(model, ve.getMsg());
        } catch (Exception e) {
            LogUtil.get(this.getClass()).error("update obj error : {}", e);
            setModuleStatusError(model, "更新失败");
        }
        setModuleEdit(model);
        model.addAttribute(Web.OBJ, obj);
        return getUrlBase().concat("-edit");
    }

    /**
     * 重置密码跳转页面.
     */
    @PreAuthorize("hasAuthority('admin:user:repassword')")
    @RequestMapping(value = "resetpwd", method = RequestMethod.GET)
    public String resetpwd() {
        return getUrlBase().concat("-resetpwd");
    }

    /**
     * 管理员重置密码
     */
    @PreAuthorize("hasAuthority('admin:user:repassword')")
    @ResponseBody
    @RequestMapping(value = "resetpwds", method = RequestMethod.POST, produces = {"application/json;charset=UTF-8"})
    public JsonVo resetpwds(@RequestBody AdminUser obj, Model model) {
        try {
            if (CommUtils.isEmpty(obj.getUsername())) {
                throw new ValidateException("请求非法");
            }
            AdminUser objDb = adminUserService.findOne(obj.getUsername());
            objDb.setUpdatedTime(CommUtils.getDayTimestamp());
            objDb.setUpdatedBy(getSessionUserName());
            objDb.setPassword(CommUtils.getMd5("123456"));
            getBaseService().save(objDb);
            return new JsonVo(true, "操作成功");
        } catch (Exception ve) {
            return new JsonVo(true, "重置失败");
        }
    }

    /**
     * 重置密码逻辑.
     */
    @PreAuthorize("hasAuthority('admin:user:repassword')")
    @ResponseBody
    @RequestMapping(value = "resetpwd", method = RequestMethod.POST, produces = {"application/json;charset=UTF-8"})
    public JsonVo resetpwd(@RequestBody AdminUser obj, Model model) {
        try {
            // ObjectValidator.validate(obj); //使用这句配置catch模块也可以完成验证
            if (obj == null || StringUtils.isEmpty(obj.getPassword()) || StringUtils.isEmpty(obj.getPasswordNew())
                || StringUtils.isEmpty(obj.getPasswordNewRepet())
                ) {
                throw new ValidateException("填写非法");
            } else if (!obj.getPasswordNew().equals(obj.getPasswordNewRepet())) {
                throw new ValidateException("2次新密码不一样");
            } else if (obj.getPasswordNew().equals(obj.getPassword())) {
                throw new ValidateException("密码相同，无需修改!");
            }

            AdminUser objDb = adminUserService.findOne(SpringSecurityUtil.getCurrentUserName());
//			System.out.println(CommUtils.getMd5(obj.getPassword()));
            if (objDb == null) {
                setModuleAdd(model);
                return new JsonVo(false, "用户不存在");
            } else if (!objDb.getPassword().equals(CommUtils.getMd5(obj.getPassword()))) {
                throw new ValidateException("密码错误!");
            }
            objDb.setUpdatedTime(CommUtils.getDayTimestamp());
            objDb.setUpdatedBy(getSessionUserName());
            objDb.setPassword(CommUtils.getMd5(obj.getPasswordNew()));
            setModuleStatusOK(model);
            getBaseService().save(objDb);
            return new JsonVo(true, "操作成功");
        } catch (ValidateException ve) {
            return new JsonVo(false, ve.getMsg());
        } catch (Exception e) {
            LogUtil.get(this.getClass()).error("update obj error : {}", e);
            return new JsonVo(false, "操作失败");
        }
    }

    /**
     * 根据传入的数据ids,来删除对象. headers =
     * {"Accept=application/json","Content-type=application/json" } , produces =
     * "application/json"
     */
//	@RequiresPermissions("admin:user:remove")
    @PreAuthorize("hasAuthority('admin:user:remove')")
    @RequestMapping(value = Web.URL_SEP_REMOVE, method = RequestMethod.POST)
    @ResponseBody
    @Override
    public JsonVo remove(@RequestBody DeleteVo<String> dvo) {
        try {
            if (dvo != null && dvo.getIds() != null && dvo.getIds().size() > 0) {
                return super.remove(dvo);
            }
            return new JsonVo(true);
        } catch (Exception e) {
            LogUtil.get(this.getClass()).error("remove erro ", e);
            return new JsonVo(false, "删除出现异常");
        }
    }

    /**
     * 跳转到更新页面.
     *
     * @param id    待更新的对象ID
     * @param model a holder for model attributes 数据
     * @return 更新页面
     */
//	@RequiresPermissions("admin:user:role")
    @PreAuthorize("hasAuthority('admin:user:role')")
    @RequestMapping(value = "role/{id}", method = RequestMethod.GET)
    protected String role(@PathVariable String id, Model model) {
        setModuleEdit(model);
        AdminUser objDb = getBaseService().findOne(id);
        model.addAttribute(Web.OBJ, objDb);
        setAllRolesInfo(id, model);
        return getUrlBase().concat("-role");
    }

    private void setAllRolesInfo(String id, Model model) {
        //查询角色下的权限列表
        List<String> roles = SpringUtil.getApplicationContext().getBean(AdminRoleService.class).fingAllRolesByUsername(id);
        if (roles == null) {
            roles = new ArrayList<String>();
        }
        List<KvVo> allRoles = adminRoleService.findAllRoles();
        if (null != roles && roles.size() > 0) {
            model.addAttribute("roles", roles.get(0));
        } else {
            model.addAttribute("roles", "");
        }
        model.addAttribute("allRoles", allRoles);
    }

    /**
     * Post 更新对象.
     */
    @PreAuthorize("hasAuthority('admin:user:role')")
    @RequestMapping(value = "role", method = {RequestMethod.POST})
    private String role(@Valid AdminUserRoleBo obj, BindingResult result, Model model) {
        try {
            setModuleEdit(model);
            model.addAttribute(Web.OBJ, obj);
            if (result.hasErrors()) {
                List<ObjectError> list = result.getAllErrors();
                for (ObjectError error : list) {
                    if (StringUtils.isNotEmpty(error.getDefaultMessage())) {
                        throw new ValidateException(error.getDefaultMessage());
                    }
                }
            }
            AdminUser objDb = getBaseService().findOne(obj.getUsername());
            if (objDb == null) {
                setModuleAdd(model);
                setModuleStatusError(model, "授权失败，用户不存在!");
                return getUrlBase().concat("-role");
            }
            String[] roleCodes = obj.getRoleCodes().split(",");//所有的权限列表
            AdminUserService adminUserService = (AdminUserService) this.getBaseService();
            adminUserService.removeUserRoles(obj.getUsername(), roleCodes);
            setModuleStatusOK(model, "授予角色成功");
        } catch (ValidateException ve) {
            setModuleStatusError(model, ve.getMsg());
        } catch (Exception e) {
            LogUtil.get(this.getClass()).error("update obj error : {}", e);
            setModuleStatusError(model, "授予角色失败");
        } finally {
        }
        return role(obj.getUsername(), model);
    }

    /**
     * 个人信息页面.
     */
    @RequestMapping(value = "info", method = RequestMethod.POST, produces = {"application/json;charset=UTF-8"})
    @ResponseBody
    public JsonMapVo info() {
        try {
            AdminUser user = this.adminUserService.findOneByUsername(getSessionUserName());
            Map<Object, Object> map = new HashMap<Object, Object>();
            map.put("username", user.getUsername());
            map.put("email", user.getEmail());
            map.put("mobile", user.getMobile());
            map.put("status", getStatusStr(user.getStatus()));
            return new JsonMapVo(map);
        } catch (Exception e) {
            LogUtil.get(this.getClass()).error("remove erro ", e);
            return new JsonMapVo(false, "查询出错");
        }
    }

    /**
     * 获取状态的字符串.
     *
     * @return 0:冻结封号、1:注册、2:资料未完善
     */
    private String getStatusStr(byte b) {
        switch (b) {
            case 0:
                return "冻结封号";
            case 1:
                return "注册";
            case 2:
                return "资料未完善";
            default:
                return "";
        }
    }

    @Override
    protected BaseService<AdminUser, String> getBaseService() {
        return adminUserService;
    }

    @Override
    protected String getUrlBase() {
        return "admin/authority/user";
    }


}
